import ref from 'ref'
import ffi from 'ffi'
import StructType from 'ref-struct'
import FaceBase from './FaceBase'

let OrientPriority = {
  AFD_FSDK_OPF_0_ONLY: 0x1, // 0 0 ...
  AFD_FSDK_OPF_90_ONLY: 0x2, // 90 90 ...
  AFD_FSDK_OPF_270_ONLY: 0x3, // 270 270 ...
  AFD_FSDK_OPF_180_ONLY: 0x4, // 180 180 ...
  AFD_FSDK_OPF_0_HIGHER_EXT: 0x5 // 0 90 270 180 0 90 270 180 ...
}

let OrientCode = {
  AFD_FSDK_FOC_0: 0x1, // 0 degree
  AFD_FSDK_FOC_90: 0x2, // 90 degree
  AFD_FSDK_FOC_270: 0x3, // 270 degree
  AFD_FSDK_FOC_180: 0x4, // 180 degree
  AFD_FSDK_FOC_30: 0x5, // 30 degree
  AFD_FSDK_FOC_60: 0x6, // 60 degree
  AFD_FSDK_FOC_120: 0x7, // 120 degree
  AFD_FSDK_FOC_150: 0x8, // 150 degree
  AFD_FSDK_FOC_210: 0x9, // 210 degree
  AFD_FSDK_FOC_240: 0xa, // 240 degree
  AFD_FSDK_FOC_300: 0xb, // 300 degree
  AFD_FSDK_FOC_330: 0xc // 330 degree
}

let AFD_FSDK_Version = StructType({
  lCodebase: FaceBase.MInt32,
  lMajor: FaceBase.MInt32,
  lMinor: FaceBase.MInt32,
  lBuild: FaceBase.MInt32,
  Version: FaceBase.MPChar,
  BuildDate: FaceBase.MPChar,
  CopyRight: FaceBase.MPChar
})

let AFD_FSDK_FACERES = StructType({
  nFace: FaceBase.MInt32,
  rcFace: FaceBase.MIntPtr_t,
  lfaceOrient: FaceBase.MIntPtr_t
})

let LPAFD_FSDK_FACERES = StructType({
  pointer: ref.refType(AFD_FSDK_FACERES)
})

let libname = './libs/libarcsoft_fsdk_face_detection.dll'
let Library = ffi.Library(libname, {
  'AFD_FSDK_GetVersion': [ref.refType(AFD_FSDK_Version), [FaceBase.MHandleType]],
  'AFD_FSDK_InitialFaceEngine': [FaceBase.MLong, [FaceBase.MPChar, FaceBase.MPChar, FaceBase.MHandleType, FaceBase.MInt32, FaceBase.MHandleRefType, FaceBase.MInt32, FaceBase.MInt32, FaceBase.MInt32]],
  'AFD_FSDK_UninitialFaceEngine': [FaceBase.MLong, [FaceBase.MHandleType]],
  'AFD_FSDK_StillImageFaceDetection': [FaceBase.MLong, [FaceBase.MHandleType, ref.refType(FaceBase.ASVLOFFSCREEN), ref.refType(LPAFD_FSDK_FACERES)]]
})

function _process(hEngine, asvl, result_callback) {
  let pFaceRes = new LPAFD_FSDK_FACERES()
  pFaceRes.pointer = ref.NULL
  let ppFaceRes = pFaceRes.ref()
  let ret = Library.AFD_FSDK_StillImageFaceDetection(hEngine, asvl.ref(), ppFaceRes)
  if (ret !== 0) {
    console.log('AFD_FSDK_StillImageFaceDetection ret: ' + ret)
    result_callback(0, asvl, {nFace: 0, info: []})
  } else {
    let pFaceRes = ppFaceRes.deref()
    let faceRes = pFaceRes.pointer.deref()
    let faces = {}
    faces.nFace = faceRes.nFace
    faces.info = []
    if (faceRes.nFace !== 0) {
      let rect = new FaceBase.MRECT()
      let orientBuffer = Buffer.alloc(FaceBase.MInt32.size)
      for (let i = 0; i < faceRes.nFace; i++) {
        FaceBase.memcpy(ref.address(rect.ref()), faceRes.rcFace + FaceBase.MRECT.size * i, FaceBase.MRECT.size)
        FaceBase.memcpy(ref.address(orientBuffer), faceRes.lfaceOrient + FaceBase.MInt32.size * i, FaceBase.MInt32.size)
        let _orient = orientBuffer.readInt32LE(0)
        faces.info.push({left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom, orient: _orient})
      }
    }
    result_callback(0, asvl, faces)
  }
}

exports.OrientPriority = OrientPriority
exports.OrientCode = OrientCode
exports.AFD_FSDK_Version = AFD_FSDK_Version
exports.AFD_FSDK_FACERES = AFD_FSDK_FACERES
exports.LPAFD_FSDK_FACERES = LPAFD_FSDK_FACERES
exports.AFD_FSDK_GetVersion = Library.AFD_FSDK_GetVersion
exports.AFD_FSDK_InitialFaceEngine = Library.AFD_FSDK_InitialFaceEngine
exports.AFD_FSDK_UninitialFaceEngine = Library.AFD_FSDK_UninitialFaceEngine
exports.AFD_FSDK_StillImageFaceDetection = Library.AFD_FSDK_StillImageFaceDetection
exports.process = _process
